<template>
    <!-- 人工智能AI助手 -->
    <div id="ai-global-toolbar">
      <!-- 弹出窗口 -->
      <div :class="isOpen ? 'ai-toolbar-wrap ai-toolbar-pen' : 'ai-toolbar-wrap'">
        <!--内层容器，包含弹出工具区域和工具按钮 定位是relative-->
        <div class="ai-toolbar-container">
          <div class="ai-toolbar-panel">
            <!-- 聊天窗口 -->
            <div class="ai-chat-container">
              <!-- 聊天标题 -->
              <div class="ai-title-panel">
                <div class="title">
                  <h4>欢迎使用AI助手</h4>
                  <span class="test">内测版</span>
                </div>
                <div>
                  大语言模型来自：<a
                    href="https://www.deepseek.com/"
                    target="blank"
                    >DeepSeek-R1</a
                  >
                </div>
              </div>
              <!-- 聊天内容框 -->
              <div class="ai-chat-content">
                <ChatDialogComponents 
                  :AI_OutList="ai_outputList" 
                  :AI_StopByUser="isStoppedByUser"
                />
              </div>
            </div>
            <!-- 聊天输入 -->
            <div class="ai-chat-input-panel">
              <div class="ai-loading" v-if="ai_loading">AI思考中...点击发送按钮停止输出</div>
              <div class="ai-input-commit">
                <el-input
                  class="chat-input"
                  placeholder="请输入你的问题,并按Enter提问"
                  v-model="user_input"
                  @keyup.enter="NewStreamChat"
                  clearable
                  :disabled="ai_loading"
                />
                <!-- 替换原来的按钮为新的样式 -->
                <div class="ds-button-area">
                  <div v-if="!ai_loading" class="send-area" @click="NewStreamChat">
                    <div class="ds-icon">
                      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
                        <path fill="currentColor" d="m64 448 832-320-128 704-446.08-243.328L832 192 242.816 545.472zm256 512V657.024L512 768z"></path>
                      </svg>
                    </div>
                  </div>
                  <div v-else class="send-area" @click="stopOutput">
                    <div class="ds-icon-stop"></div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div class="ai-toolbar-buttons">
            <div class="ai-tbar-list">
              <div class="ai-tbar-item" @click="openAIWindows">
                <i class="tbar_icon">Ai</i>
                <em class="tab-text">AI助手</em>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </template>
  
  <script setup>
  import { ref, reactive, computed, onMounted, nextTick } from "vue";
  import ChatDialogComponents from "@/components/ChatDialogComponents.vue";
  
  // 系统提示词
  const SYSTEM_PROMPT = {
    role: "system",
    content:
      "你是一个由深度求索公司开发的人工智能助手,名为deepseek-R1。你非常专业、友好且富有同理心。你会以简洁清晰的方式回答问题,并始终保持谦逊和真诚。当你不确定某件事时,你会坦诚地承认。你会避免任何有害或不当的内容。",
  };
  
  const isOpen = ref(false);
  const user_input = ref("");
  const ai_output = ref("");
  const ai_outputList = ref([]);
  const ai_loading = ref(false);
  const init_message = ref([]);
  const isStoppedByUser = ref(false);
  const startTime = ref(0);
  const totalTokens = ref(0);
  
  const openAIWindows = () => {
    isOpen.value = !isOpen.value;
  };
  
  const scrollToBottom = () => {
    nextTick(() => {
      var container = document.querySelector(".ai-chat-content");
      container.scrollTop = container.scrollHeight;
    });
  };
  
  const replaceMathSymbols = (inputStr) => {
    let replacedStr;
    replacedStr = inputStr
      .replace(/\\\[(\s*)/g, "$$")
      .replace(/(\s*)\\\]/g, "$$");
    replacedStr = replacedStr
      .replace(/\\\((\s*)/g, "$")
      .replace(/(\s*)\\\)/g, "$");
    return replacedStr;
  };
  
  const processAIResponse = (content, isCompleting = false) => {
    const thinkEndIndex = content.indexOf("</think>");
    let thinking = content;
    let answer = "";
    let isThinkedAnswer = false;
  
    if (thinkEndIndex > -1) {
      thinking = content.slice(0, thinkEndIndex).trim();
      answer = content.slice(thinkEndIndex + 8).trim();
      isThinkedAnswer = true;
    } else if (isCompleting) {
      thinking = "";
      answer = content;
      isThinkedAnswer = false;
    }
  
    return {
      thinking,
      answer,
      isThinkedAnswer,
      isStopped: isStoppedByUser.value,
    };
  };
  
  const NewStreamChat = async () => {
    if (ai_loading.value || !user_input.value.trim()) return;
  
    isStoppedByUser.value = false;
    ai_loading.value = true;
    startTime.value = Date.now();
    totalTokens.value = 0;
  
    try {
      const prompt = user_input.value;
      user_input.value = "";
      ai_output.value = "";
      
      // 添加用户消息到显示列表和对话历史
      const userMessage = { role: "user", content: prompt };
      ai_outputList.value.push(userMessage);
      init_message.value.push(userMessage);
      
      scrollToBottom();
  
      const response = await fetch("http://localhost:8000/v1/chat/completions", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          messages: init_message.value,
          max_tokens: 2048,
          temperature: 0.1,
          stream: true,
        }),
      });
  
      if (!response.body) {
        throw new Error("服务器未返回流数据");
      }
  
      const reader = response.body.getReader();
      const decoder = new TextDecoder("utf-8");
      let buffer = "";
  
      ai_outputList.value.push({ role: "assistant", content: "" });
  
      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          break;
        }
        const chunk = decoder.decode(value, { stream: true });
        // console.log("流数据：", chunk);
  
        buffer += chunk;
  
        const lines = buffer.split("\n");
        buffer = lines.pop();
        for (const line of lines) {
          if (line.startsWith("data: ")) {
            const jsonStr = line.slice(6).trim();
            if (jsonStr !== "[DONE]") {
              try {
                const jsonData = JSON.parse(jsonStr);
                const content = jsonData?.choices[0]?.delta?.content || "";
                if (content) {
                  totalTokens.value += content.length;
                  const newContent = ai_output.value + content;
                  const { thinking, answer, isThinkedAnswer } = processAIResponse(newContent, false);
  
                  ai_output.value += content;
                  const lastMsg = ai_outputList.value[ai_outputList.value.length - 1];
                  lastMsg.content += content;
                  lastMsg.content = replaceMathSymbols(lastMsg.content);
                  lastMsg.thinking = thinking;
                  lastMsg.answer = answer;
                  lastMsg.isThinkedAnswer = isThinkedAnswer;
                  lastMsg.isThinkingExpand = true;
  
                  scrollToBottom();
                }
              } catch (error) {
                console.error("解析 JSON 数据失败:", error, line);
              }
            } else {
              const lastMsg = ai_outputList.value[ai_outputList.value.length - 1];
              lastMsg.isCompleted = true;
              const endTime = Date.now();
              const duration = (endTime - startTime.value) / 1000;
              lastMsg.tokenRate = Math.round(totalTokens.value / duration);
  
              init_message.value.push({
                role: "assistant",
                content: ai_output.value,
              });
              scrollToBottom();
            }
          }
        }
      }
      ai_outputList.value[ai_outputList.value.length - 1].content =
        replaceMathSymbols(
          ai_outputList.value[ai_outputList.value.length - 1].content
        );
      ai_loading.value = false;
    } catch (error) {
      console.error("流数据请求失败:", error);
    } finally {
      ai_loading.value = false;
    }
  };
  
  const stopOutput = async () => {
    if (!ai_loading.value) return;
  
    isStoppedByUser.value = true;
    ai_loading.value = false;
  
    const endTime = Date.now();
    const duration = (endTime - startTime.value) / 1000;
    const tokenRate = Math.round(totalTokens.value / duration);
  
    const lastMsg = ai_outputList.value[ai_outputList.value.length - 1];
    if (lastMsg) {
      lastMsg.isCompleted = true;
      lastMsg.tokenRate = tokenRate;
      lastMsg.isStopped = true;
    }
  
    await fetch("http://localhost:8000/api/stop_generation", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ confirm: true }),
    });
  };
  
  onMounted(() => {
    init_message.value = [SYSTEM_PROMPT];
  });
  </script>
  
  <style scoped>
  #ai-global-toolbar {
    display: block;
  }
  .ai-toolbar-wrap {
    position: fixed;
    height: 100%;
    top: 0;
    right: -600px;
    z-index: 2999;
    transition: right 0.5s;
  }
  
  .ai-toolbar-pen {
    right: 0px;
  }
  
  .ai-toolbar-container {
    position: relative;
    width: 600px;
    height: 100%;
  }
  
  .ai-toolbar-panel {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    width: 600px;
    height: 100%;
    background-color: #fcfbfb;
    border-left: solid 4px rgb(74, 175, 241);
    z-index: 99;
  }
  
  .ai-toolbar-buttons {
    position: absolute;
    top: 0;
    left: 1px;
    height: 100%;
  }
  
  .ai-tbar-list {
    position: absolute;
    top: 50%;
    right: 0;
    margin-top: -61px;
    width: 35px;
  }
  
  .ai-tbar-item {
    position: relative;
    width: 35px;
    height: 35px;
    margin-bottom: 1px;
    cursor: pointer;
    text-align: center;
    line-height: 35px;
    border-radius: 3px 0 0 3px;
  }
  
  .ai-tbar-item .tbar_icon {
    position: relative;
    z-index: 5;
    width: 34px;
    height: 35px;
    display: block;
    margin-left: 1px;
    background-color: rgb(140, 143, 145);
    border: solid 1px rgba(255, 255, 255, 1);
    border-radius: 5px 0 0 5px;
    color: #ffffff;
    font-size: 20px;
  }
  
  .ai-tbar-item .tbar_icon:hover {
    background-color: rgb(74, 175, 241);
    border-left: solid 1px rgba(255, 255, 255, 0);
    border-radius: 0;
  }
  
  .tab-text {
    width: 62px;
    height: 35px;
    line-height: 35px;
    color: #fff;
    text-align: center;
    font-family: 微软雅黑;
    position: absolute;
    left: 35px;
    font-size: 12px;
    font-style: normal;
    z-index: 4;
    top: 0;
    background-color: rgb(74, 175, 241);
    border: solid 1px #ffffff;
    border-radius: 5px 0 0 5px;
    border-radius: 3px 0 0 3px;
    transition: left 0.3s;
  }
  
  .ai-tbar-item .tbar_icon:hover + .tab-text {
    left: -60px;
  }
  
  /* AI区域内容样式 */
  /* 标题部分 */
  .ai-title-panel {
    display: flex;
    flex-direction: column;
    width: 100%;
    margin-bottom: 30px;
  }
  
  .ai-title-panel > div {
    display: flex;
    justify-content: center;
    font-size: 12px;
  }
  
  .title {
    position: relative;
    margin-top: 30px;
    display: flex;  /* 添加 flex 布局 */
    align-items: center;  /* 垂直居中对齐 */
    justify-content: center;  /* 水平居中对齐 */
  }
  
  .title h4 {
    font-weight: 700;
    margin: 0;  /* 移除默认外边距 */
    font-size: 22px;
    line-height: 1.5;  /* 调整行高 */
  }
  
  .title .test {
    border: 1px solid rgb(3, 150, 248);
    color: rgb(3, 150, 248);
    border-radius: 3px;
    padding: 0 3px;
    height: 18px;
    line-height: 18px;
    margin-left: 5px;
    font-size: 12px;  /* 调整字体大小 */
    display: inline-flex;  /* 使用 inline-flex */
    align-items: center;  /* 垂直居中 */
  }
  
  /* 内容部分 */
  .ai-chat-content {
    position: relative;
    padding: 10px 10px;
    background: #ffffff;
    height: calc(100vh - 115px - 150px);
    overflow-y: auto;
    font-size: 16px;
    color: #000;
  }
  
  .chat-dialog {
    padding: 0 10px;
  }
  
  /* 动态html样式不生效 */
  :deep(.question) {
    font-weight: 700;
    margin-top: 10px;
  }
  /* 聊天输入 */
  
  .ai-chat-input-panel {
    display: flex;
    flex-direction: column;
    margin-bottom: 70px;
    padding: 10px;
  }
  
  .ai-loading {
    font-size: 15px;
    line-height: 16px;
    margin: 10px 0;
    color: #666;
    font-size: 13px;
    text-align: center;
    margin-bottom: 8px;
  }
  
  .ai-input-commit {
    display: flex;
    width: 100%;
  }
  
  .ds-button-area {
    white-space: nowrap;
  }
  
  .send-area {
    white-space: nowrap;
    cursor: pointer;
    color: #fff;
    background: #4d6bfe;
    border: none;
    border-radius: 6px;
    flex-direction: column;
    flex-shrink: 0;
    justify-content: center;
    align-items: center;
    min-width: 32px;
    height: 32px;
    margin-top: auto;
    display: flex;
  }
  
  .send-area:hover {
    background: #2563eb;
  }
  
  .ds-icon {
    font-size: 16px;
    width: 16px;
    height: 16px;
  }
  
  .ds-icon svg {
    width: 100%;
    height: 100%;
  }
  
  .ds-icon-stop {
    width: 12px;
    height: 12px;
    background: rgb(252, 250, 250);
    border-radius: 2px;
  }
  
  /* 调整输入框样式以配合新按钮 */
  .chat-input {
    margin-right: 8px;
  }
  
  /* 移除旧的按钮样式 */
  .ai-button {
    display: none;
  }
  
  a {
    text-decoration: none;
  }
  
  a:hover {
    color: #f15323;
  }
  
  /* 自定义滚动条的整体样式 */
  ::-webkit-scrollbar {
    width: 12px;
  }
  
  /* 自定义滚动轨迹的样式 */
  ::-webkit-scrollbar-track {
    background: #f1f1f1;
  }
  
  /* 自定义滚动滑块的样式 */
  ::-webkit-scrollbar-thumb {
    background-color: rgb(99, 188, 247);
    border-radius: 6px;
    border: 3px solid transparent;
    background-clip: content-box;
  }
  
  /* 当鼠标悬停在滚动滑块上时的样式 */
  ::-webkit-scrollbar-thumb:hover {
    background-color: rgb(45, 165, 246);
  }
  
  /* 添加停止按钮样式 */
  .stop-icon {
    width: 14px;
    height: 14px;
    background: rgb(252, 250, 250);
    border-radius: 2px;
  }
  
  /* 禁用状态的输入框样式 */
  :deep(.el-input.is-disabled .el-input__inner) {
    background-color: #f5f7fa;
    border-color: #e4e7ed;
    color: #c0c4cc;
    cursor: not-allowed;
  }
  </style>